package cn.qicaiwang.open.admin.controller.personal;

import cn.hutool.core.util.StrUtil;
import cn.qicaiwang.open.common.annotation.Log;
import cn.qicaiwang.open.common.annotation.RepeatSubmit;
import cn.qicaiwang.open.common.constant.Constants;
import cn.qicaiwang.open.common.controller.BaseController;
import cn.qicaiwang.open.common.entity.LoginUser;
import cn.qicaiwang.open.common.enums.BusinessType;
import cn.qicaiwang.open.common.enums.ResultStatusCodeEnum;
import cn.qicaiwang.open.common.enums.SmsCodeEnum;
import cn.qicaiwang.open.common.response.ResponseResult;
import cn.qicaiwang.open.common.utils.AesUtil;
import cn.qicaiwang.open.common.utils.SecurityUtil;
import cn.qicaiwang.open.system.model.dto.*;
import cn.qicaiwang.open.system.model.entity.*;
import cn.qicaiwang.open.system.model.req.LoginLogREQ;
import cn.qicaiwang.open.system.model.req.OperateLogREQ;
import cn.qicaiwang.open.system.model.vo.SystemRoleVO;
import cn.qicaiwang.open.system.model.vo.SystemRouter;
import cn.qicaiwang.open.system.service.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 个人中心
 */
@Slf4j
@RestController
@RequestMapping("personal")
public class PersonalController extends BaseController {
    @Autowired
    private ISystemUserService systemUserService;
    @Autowired
    private ISystemRoleService systemRoleService;
    @Autowired
    private ISystemMenuService systemMenuService;
    @Autowired
    private ISystemUnitService systemUnitService;
    @Autowired
    private ISystemUserWechatService systemUserWechatService;
    @Autowired
    private ISystemOperLogService systemOperLogService;
    @Autowired
    private ISystemLoginLogService systemLoginLogService;
    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 获取用户信息
     * @return
     */
    @GetMapping("getInfo")
    @Log(title = "个人中心", businessType = BusinessType.SELECT)
    public ResponseResult getInfo(){
        LoginUser currentUser = getCurrentUser();
        SystemUser systemUser = systemUserService.getById(currentUser.getId());
        BeanUtils.copyProperties(systemUser, currentUser);
        // 角色集合
        Set<SystemRoleVO> roles = new HashSet<>();
        // 权限集合
        Set<String> permissions = new HashSet<>();
        if (currentUser.isAdmin()) {
            roles.add(new SystemRoleVO("0", "超级管理员", Constants.SUPER_ADMIN_ROLE));
            permissions.add("*:*:*");
        } else {
            List<SystemRole> systemRoles = systemRoleService.selectListByUserId(currentUser.getId());
            for (int i = 0; i < systemRoles.size(); i++) {
                SystemRole item = systemRoles.get(i);
                roles.add(new SystemRoleVO(item.getId(), item.getRoleName(), item.getRolePerm()));
            }
            List<SystemMenu> systemMenus = systemMenuService.selectListByUserId(currentUser.getId());
            for (int i = 0; i < systemMenus.size(); i++) {
                SystemMenu item = systemMenus.get(i);
                permissions.add(item.getPerms());
            }
        }

        SystemUnit systemUnits = systemUnitService.getById(currentUser.getUnitId());

        SystemUserWechat wechat = systemUserWechatService.selectOneByUserId(currentUser.getId());

        Map<String, Object> data = new HashMap();
        data.put("userInfo", currentUser);
        data.put("units", systemUnits);
        data.put("roles", roles);
        data.put("permissions", permissions);
        data.put("wechat", wechat);
        return ResponseResult.ok(data);
    }

    @GetMapping("getRouters/{rolePerm}")
    @Log(title = "个人中心", businessType = BusinessType.SELECT)
    public ResponseResult getRouters(@PathVariable String rolePerm){
        List<SystemRouter> routers = systemMenuService.getRouters(rolePerm);
        return ResponseResult.ok(routers);
    }

    @GetMapping("getPermissions")
    @Log(title = "个人中心", businessType = BusinessType.SELECT)
    public ResponseResult getPermissions(){
        return ResponseResult.ok(getCurrentUser().getPermissions());
    }

    /**
     * 修改个人信息
     *
     * @param systemUserDTO
     * @return
     */
    @RepeatSubmit
    @PostMapping(value = "updatePersonal")
    @Log(title = "个人中心", businessType = BusinessType.UPDATE)
    public ResponseResult updatePersonal(@RequestBody SystemUserDTO systemUserDTO) {
        if(systemUserDTO == null || StrUtil.isBlank(systemUserDTO.getId())){
            return ResponseResult.error(ResultStatusCodeEnum.PARAM_REQUIRE_ERROR);
        }
        if(StrUtil.isNotBlank(systemUserDTO.getPhone())) {
            SystemUser systemUser = systemUserService.selectOneByMobile(systemUserDTO.getPhone());
            if(systemUser != null && !systemUser.getId().equals(systemUserDTO.getId())){
                return ResponseResult.error(ResultStatusCodeEnum.MOBILE_BINDED);
            }
        }
        SystemUser systemUser = new SystemUser();
        systemUser.setId(getCurrentUserId());
        systemUser.setRealName(systemUserDTO.getRealName());
        systemUser.setEmail(systemUserDTO.getEmail());
        systemUser.setPhone(systemUserDTO.getPhone());
        systemUser.setGender(systemUserDTO.getGender());
        systemUser.setAvatar(systemUserDTO.getAvatar());
        boolean b = systemUserService.updateById(systemUser);
        if(b){
            return ResponseResult.ok();
        }
        return ResponseResult.error(ResultStatusCodeEnum.HTTP_ERROR);
    }

    /**
     * 修改密码
     *
     * @return
     */
    @RepeatSubmit
    @PostMapping(value = "updatePassword")
    @Log(title = "个人中心", businessType = BusinessType.UPDATE)
    public ResponseResult updatePassword(@RequestBody UpdatePasswordDTO updatePasswordDTO) {
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        if(StrUtil.isBlank(updatePasswordDTO.getOldPassword()) || StrUtil.isBlank(updatePasswordDTO.getNewPassword())){
            return ResponseResult.error(ResultStatusCodeEnum.PARAM_REQUIRE_ERROR);
        }
        String userId = getCurrentUserId();
        SystemUser systemUser = systemUserService.getById(userId);

        String oldPassword = AesUtil.decrypt(updatePasswordDTO.getOldPassword());
        String newPassword = AesUtil.decrypt(updatePasswordDTO.getNewPassword());

        boolean matches = passwordEncoder.matches(oldPassword, systemUser.getPassword());
        if (!matches) {
            return ResponseResult.error("旧密码不正确");
        }
        SystemUser updateUser = new SystemUser();
        updateUser.setId(userId);
        updateUser.setPassword(passwordEncoder.encode(newPassword));
        boolean b = systemUserService.updateById(updateUser);
        if(b){
            return ResponseResult.ok();
        }
        return ResponseResult.error(ResultStatusCodeEnum.HTTP_ERROR);
    }

    /**
     * 修改手机号
     * @param updateMobileDTO
     * @return
     */
    @PostMapping("updateMobile")
    public ResponseResult updateMobile(@RequestBody UpdateMobileDTO updateMobileDTO){
        String userId = SecurityUtil.getUserId();

        if(StrUtil.isBlank(updateMobileDTO.getMobile())){
            return ResponseResult.error(ResultStatusCodeEnum.MOBILE_NOT_EMPTY);
        }
        if(StrUtil.isBlank(updateMobileDTO.getCaptcha())){
            return ResponseResult.error(ResultStatusCodeEnum.CAPTCHA_NOT_EMPTY);
        }

        String mobile = AesUtil.decrypt(updateMobileDTO.getMobile());

        SystemUser bizMember = systemUserService.selectOneByMobile(mobile);
        if(bizMember != null && !bizMember.getId().equals(userId)){
            return ResponseResult.error(ResultStatusCodeEnum.MOBILE_BINDED);
        }

        String captcha = redisTemplate.opsForValue().get(SmsCodeEnum.MODIFY_MOBILE.getKey() + mobile);
        if(!updateMobileDTO.getCaptcha().equalsIgnoreCase(captcha)){
            return ResponseResult.error(ResultStatusCodeEnum.CAPTCHA_ERROR);
        }

        SystemUser temp = new SystemUser();
        temp.setId(userId);
        temp.setPhone(mobile);
        boolean flag = systemUserService.updateById(temp);
        if(flag){
            return ResponseResult.ok();
        }
        return ResponseResult.error(ResultStatusCodeEnum.HTTP_ERROR);
    }

    /**
     * 修改邮箱
     * @param updateEmailDTO
     * @return
     */
    @PostMapping("updateEmail")
    public ResponseResult updateEmail(@RequestBody UpdateEmailDTO updateEmailDTO){
        String userId = SecurityUtil.getUserId();

        if(StrUtil.isBlank(updateEmailDTO.getEmail())){
            return ResponseResult.error(ResultStatusCodeEnum.MOBILE_NOT_EMPTY);
        }
        if(StrUtil.isBlank(updateEmailDTO.getCaptcha())){
            return ResponseResult.error(ResultStatusCodeEnum.CAPTCHA_NOT_EMPTY);
        }

        String email = AesUtil.decrypt(updateEmailDTO.getEmail());

        SystemUser bizMember = systemUserService.selectOneByEmail(email);
        if(bizMember != null && !bizMember.getId().equals(userId)){
            return ResponseResult.error(ResultStatusCodeEnum.EMAIL_BINDED);
        }

        String captcha = redisTemplate.opsForValue().get(SmsCodeEnum.MODIFY_EMAIL.getKey() + updateEmailDTO.getEmail());
        if(!updateEmailDTO.getCaptcha().equalsIgnoreCase(captcha)){
            return ResponseResult.error(ResultStatusCodeEnum.CAPTCHA_ERROR);
        }

        SystemUser temp = new SystemUser();
        temp.setId(userId);
        temp.setEmail(email);
        boolean flag = systemUserService.updateById(temp);
        if(flag){
            return ResponseResult.ok();
        }
        return ResponseResult.error(ResultStatusCodeEnum.HTTP_ERROR);
    }

    /**
     * 修改头像
     * @param updateAvatarDTO
     * @return
     */
    @RepeatSubmit
    @PostMapping(value = "updateAvatar")
    @Log(title = "个人中心", businessType = BusinessType.UPDATE)
    public ResponseResult updateAvatar(@RequestBody UpdateAvatarDTO updateAvatarDTO) {
        if(StrUtil.isBlank(updateAvatarDTO.getId()) || StrUtil.isBlank(updateAvatarDTO.getAvatar())){
            return ResponseResult.error(ResultStatusCodeEnum.PARAM_REQUIRE_ERROR);
        }
        String userId = getCurrentUserId();
        SystemUser updateUser = new SystemUser();
        updateUser.setId(userId);
        updateUser.setAvatar(updateAvatarDTO.getAvatar());
        boolean b = systemUserService.updateById(updateUser);
        if(b){
            return ResponseResult.ok();
        }
        return ResponseResult.error(ResultStatusCodeEnum.HTTP_ERROR);
    }

    /**
     * 个人操作日志
     * @param page
     * @param operateLogREQ
     * @return
     */
    @GetMapping(value = "logger/operate/page")
        public ResponseResult operateLoggerPage(Page page, OperateLogREQ operateLogREQ){
        // 获取当前的用户
        LoginUser loginUser = SecurityUtil.getCurrentUser();
        operateLogREQ.setOperName(loginUser.getUsername());
        Page<SystemOperLog> pageList = systemOperLogService.pageList(page, operateLogREQ);
        return ResponseResult.ok(pageList);
    }

    @GetMapping(value = "logger/operate/get/{id}")
    public ResponseResult operateLoggerGet(@PathVariable String id) {
        if(StrUtil.isBlank(id)){
            return ResponseResult.error(ResultStatusCodeEnum.PARAM_REQUIRE_ERROR);
        }
        SystemOperLog systemOperLog = systemOperLogService.getById(id);
        if(systemOperLog != null){
            return ResponseResult.ok(systemOperLog);
        }
        return ResponseResult.error(ResultStatusCodeEnum.DATA_NO_EXIST);
    }

    @RepeatSubmit
    @PostMapping(value = "logger/operate/delete")
    public ResponseResult operateLoggerDelete(@RequestBody List<String> ids){
        boolean b = systemOperLogService.removeByIds(ids);
        if(b){
            return ResponseResult.ok();
        }
        return ResponseResult.error(ResultStatusCodeEnum.HTTP_ERROR);
    }

    @RepeatSubmit
    @GetMapping(value = "logger/operate/clean")
    public ResponseResult operateLoggerClean(){
        // 获取当前的用户
        LoginUser loginUser = SecurityUtil.getCurrentUser();
        boolean b = systemOperLogService.cleanWithMe(loginUser.getUsername());
        if(b){
            return ResponseResult.ok();
        }
        return ResponseResult.error(ResultStatusCodeEnum.HTTP_ERROR);
    }

    /**
     * 个人登录日志
     * @param page
     * @param loginLogREQ
     * @return
     */
    @GetMapping(value = "logger/login/page")
    @Log(title = "登录日志", businessType = BusinessType.SELECT)
    public ResponseResult loginLoggerPage(Page page, LoginLogREQ loginLogREQ){
        LoginUser loginUser = SecurityUtil.getCurrentUser();
        loginLogREQ.setUserName(loginUser.getUsername());
        Page<SystemLoginLog> pageList = systemLoginLogService.pageList(page, loginLogREQ);
        return ResponseResult.ok(pageList);
    }

    @GetMapping(value = "logger/login/get/{id}")
    @Log(title = "登录日志", businessType = BusinessType.SELECT)
    public ResponseResult loginLoggerGet(@PathVariable String id) {
        if(StrUtil.isBlank(id)){
            return ResponseResult.error(ResultStatusCodeEnum.PARAM_REQUIRE_ERROR);
        }
        SystemLoginLog systemLoginLog = systemLoginLogService.getById(id);
        if(systemLoginLog != null){
            return ResponseResult.ok(systemLoginLog);
        }
        return ResponseResult.error(ResultStatusCodeEnum.DATA_NO_EXIST);
    }

    @RepeatSubmit
    @PostMapping(value = "logger/login/delete")
    @Log(title = "登录日志", businessType = BusinessType.DELETE)
    public ResponseResult loginLoggerDelete(@RequestBody List<String> ids){
        boolean b = systemLoginLogService.removeByIds(ids);
        if(b){
            return ResponseResult.ok();
        }
        return ResponseResult.error(ResultStatusCodeEnum.HTTP_ERROR);
    }

    @RepeatSubmit
    @GetMapping(value = "logger/login/clean")
    @Log(title = "登录日志", businessType = BusinessType.CLEAN)
    public ResponseResult loginLoggerClean(){
        LoginUser loginUser = SecurityUtil.getCurrentUser();
        boolean b = systemLoginLogService.cleanWithMe(loginUser.getUsername());
        if(b){
            return ResponseResult.ok();
        }
        return ResponseResult.error(ResultStatusCodeEnum.HTTP_ERROR);
    }

    @GetMapping("wechat/check")
    public ResponseResult checkWechat() {
        String userId = SecurityUtil.getUserId();
        // 查询微信是否被其它用户绑定
        if(redisTemplate.hasKey(Constants.WECHAT_BIND_PREFIX + userId)){
            String result = redisTemplate.opsForValue().get(Constants.WECHAT_BIND_PREFIX + userId);
            if(ResultStatusCodeEnum.WECHAT_BINDED.getCode().equals(result)){
                return ResponseResult.error(ResultStatusCodeEnum.WECHAT_BINDED);
            }
        }

        SystemUserWechat systemUserWechat = systemUserWechatService.selectOneByUserId(userId);
        if(systemUserWechat == null){
            return ResponseResult.error(ResultStatusCodeEnum.USER_NOT_BIND_WECHAT);
        }
        return ResponseResult.ok(systemUserWechat);
    }

    @GetMapping("wechat/unbind")
    public ResponseResult unbindWechat() {
        String userId = SecurityUtil.getUserId();
        QueryWrapper<SystemUserWechat> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        boolean b = systemUserWechatService.remove(queryWrapper);
        if(b){
            return ResponseResult.ok();
        }
        return ResponseResult.error(ResultStatusCodeEnum.HTTP_ERROR);
    }
}
